Resolves: tdf#115351 convert boolean equivalent format codes to proper Boolean

Because Excel does not know a Boolean number format, BOOLEAN is
saved to Excel as

"TRUE";"TRUE";"FALSE"

with implicit conditions [>0] and [<0]. This when loaded has no
boolean property. Then saved to ODF it is loaded as

[>0]"TRUE";[<0]"TRUE";"FALSE"

with explicit conditions, which has identical meaning.

Convert both equivalent format codes to proper BOOLEAN when
reading. Locale dependent representations are treated the same,
e.g. "WAHR";"WAHR";"FALSCH"

Change-Id: I49383d71fce972fdd7ad9b19ce3bc150d02aba62
Reviewed-on: https://gerrit.libreoffice.org/50642
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins <ci@libreoffice.org>
diff --git a/sc/qa/unit/subsequent_filters-test.cxx b/sc/qa/unit/subsequent_filters-test.cxx
index 5332bc7..6742e12 100644
--- a/sc/qa/unit/subsequent_filters-test.cxx
+++ b/sc/qa/unit/subsequent_filters-test.cxx
@@ -459,7 +459,8 @@
    ScDocShellRef xDocSh = loadDoc("check-boolean.", FORMAT_XLSX);
    ScDocument& rDoc = xDocSh->GetDocument();
    SvNumberFormatter* pNumFormatter = rDoc.GetFormatTable();
    const OUString aBooleanTypeStr = "\"TRUE\";\"TRUE\";\"FALSE\"";
    // Saved as >"TRUE";"TRUE";"FALSE"< but reading converted back to >BOOLEAN<
    const OUString aBooleanTypeStr = "BOOLEAN";

    CPPUNIT_ASSERT_MESSAGE("Failed to load check-boolean.xlsx", xDocSh.is());
    sal_uInt32 nNumberFormat;
@@ -469,7 +470,7 @@
        rDoc.GetNumberFormat(0, i, 0, nNumberFormat);
        const SvNumberformat* pNumberFormat = pNumFormatter->GetEntry(nNumberFormat);
        const OUString& rFormatStr = pNumberFormat->GetFormatstring();
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Number format != boolean", rFormatStr, aBooleanTypeStr);
        CPPUNIT_ASSERT_EQUAL_MESSAGE("Number format != boolean", aBooleanTypeStr, rFormatStr);
    }

    xDocSh->DoClose();
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index 2223e15..984c85f1 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -761,6 +761,8 @@
        , bAdditionalBuiltin( false )
        , bStarFlag( false )
{
    rScan.ReplaceBooleanEquivalent( rString);

    OUStringBuffer sBuff(rString);

    // If the group (AKA thousand) separator is a No-Break Space (French)
diff --git a/svl/source/numbers/zforscan.cxx b/svl/source/numbers/zforscan.cxx
index 3f1cf19..d9e1fba 100644
--- a/svl/source/numbers/zforscan.cxx
+++ b/svl/source/numbers/zforscan.cxx
@@ -361,6 +361,16 @@
    InitSpecialKeyword( NF_KEY_TRUE );
    InitSpecialKeyword( NF_KEY_FALSE );

    // Boolean equivalent format codes that are written to Excel files, may
    // have been written to ODF as well, specifically if such loaded Excel file
    // was saved as ODF, and shall result in proper Boolean again.
    // "TRUE";"TRUE";"FALSE"
    sBooleanEquivalent1 = "\"" + sKeyword[NF_KEY_TRUE] + "\";\"" +
        sKeyword[NF_KEY_TRUE] + "\";\"" + sKeyword[NF_KEY_FALSE] + "\"";
    // [>0]"TRUE";[<0]"TRUE";"FALSE"
    sBooleanEquivalent2 = "[>0]\"" + sKeyword[NF_KEY_TRUE] + "\";[<0]\"" +
        sKeyword[NF_KEY_TRUE] + "\";\"" + sKeyword[NF_KEY_FALSE] + "\"";

    // compatibility currency strings
    InitCompatCur();

@@ -3289,4 +3299,14 @@
    pInfo->nCntExp      = nCntExp;
}

void ImpSvNumberformatScan::ReplaceBooleanEquivalent( OUString& rString )
{
    InitKeywords();
    /* TODO: compare case insensitive? Or rather leave as is and case not
     * matching indicates user supplied on purpose? Written to file / generated
     * was always uppercase. */
    if (rString == sBooleanEquivalent1 || rString == sBooleanEquivalent2)
        rString = GetKeywords()[NF_KEY_BOOLEAN];
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svl/source/numbers/zforscan.hxx b/svl/source/numbers/zforscan.hxx
index 34e64bd..e2246f57 100644
--- a/svl/source/numbers/zforscan.hxx
+++ b/svl/source/numbers/zforscan.hxx
@@ -144,6 +144,9 @@
            return sCurString;
        }

    /// Replace Boolean equivalent format codes with proper Boolean format.
    void ReplaceBooleanEquivalent( OUString& rString );

    void SetConvertMode(LanguageType eTmpLge, LanguageType eNewLge,
            bool bSystemToSystem = false, bool bForExcelExport = false)
    {
@@ -205,6 +208,8 @@
    OUString sCurSymbol;                        // Currency symbol for compatibility format codes
    OUString sCurString;                        // Currency symbol in upper case
    OUString sCurAbbrev;                        // Currency abbreviation
    OUString sBooleanEquivalent1;               // "TRUE";"TRUE";"FALSE"
    OUString sBooleanEquivalent2;               // [>0]"TRUE";[<0]"TRUE";"FALSE"
    static const OUString sErrStr;              // String for error output

    bool bConvertMode;                          // Set in the convert mode